home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-01-02 | 31.6 KB | 1,215 lines | [TEXT/CWIE] |
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl.h
- //
- // The PopupWindow control is designed to bring up a window whenever the
- // mouse moves over the label designated as its source. Inside the window,
- // PopupWindow renders the contents of the specified URL
- //
- // In this demonstration version, a mouse click in the specified label is
- // required, pending implementatin of a mouseOver event.
- //
- // In this demonstration version, only pict files are rendered, pending
- // implementation of MSHTML to render the contents of URL's.
- //
- // In this demonstration version, the image is rendered in a rect within
- // the browser window rather than in a separate window.
- //
-
- #include "ocheaders.h"
- #include "CBaseControl.h"
- #include "CErrorControl.h" // included in header, listed here for documentation
- #include "CBaseBindStatusCallback.h" // included in header, listed here for documentation
- #include "CPopupWindowControl.h"
- #include "BDMacros.h"
- #include "BDUtils.h"
- #include "FnAssert.h"
- #include "CCPContainer.h"
- #include "CPopupWindowError.h"
- #include <stdio.h>
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::CPopupWindowControl
- //
- // constructor
- //
-
- CPopupWindowControl::CPopupWindowControl(void) : CBaseControl(), CBaseBindStatusCallback()
- {
- CCPContainer* containerObj = NULL;
- long i; // used as index
- #ifdef _DEBUG
- HRESULT returnValue;
- IUnknown* unk;
- #endif
-
- mFatalError = false; // To block action after failure.
-
- mContainerP = NULL; // These are CBaseControl instance variables and should
- mID[0] = 0; // be initialized in that constructor; but they aren't,
- // and they get used before they're set.
-
- mCookie = 0; // NOTE: if we ever actually use this for something, we need a
- // list of them, since we allow connections to more than
- // one specific sources.
-
- mSourceName = NULL;
-
- mConnectingComplete = false;
-
- for ( i = 0; i < cMaxNumSourceControls; i++ ) // Reset the source names array.
- {
- mDesiredSourceNames[i] = NULL;
- }
- mNumDesiredSources = -1;
-
- mNumFoundSources = 0;
- mIsIdling = false;
-
- mPict = NULL;
- mPictIsLoaded = false;
-
- mPopupWidth = 288; // Arbitrary for now. The Windows version sets it to the smaller
- mPopupHeight = 288; // of the browser width or 1/3 of screen size
-
- try
- {
- // Set a default name.
-
- if ( !(SetName ( cPopupControlName )) )
- throw CPopupWindowError ( DATA_ALLOCATION_ERROR );
-
- if ( !(SetSourceName ( cEmptyCString )) )
- throw CPopupWindowError ( DATA_ALLOCATION_ERROR );
-
- #ifdef _DEBUG
- // Since we're in debug code, don't add error handling here.
-
- returnValue = QueryInterface ( IID_IUnknown, (void**) &unk );
- GetObjectName ( unk, mThisName );
- #endif
-
- // Create the new connection point container object.
-
- containerObj = new CCPContainer ( cNumConnections );
- if ( !containerObj ) throw CPopupWindowError ( DATA_ALLOCATION_ERROR );
-
- // Snag the interface pointer.
-
- if ( FAILED ( containerObj->QueryInterface ( IID_IConnectionPointContainer,
- &mCPContainerP ) ) )
- throw CPopupWindowError ( NO_CNXN_PT_CONTAINER_ERROR );
-
- if ( mCPContainerP )
- {
- // Allocate the connection points. We support 1 connection point.
-
- if ( FAILED ( containerObj->AddConnectionPoint ( IID_IDidMenuEvents ) ) )
- throw CPopupWindowError ( CANT_ADD_CNXN_PT_ERROR );
- }
- }
-
- // error handling
-
- catch ( CPopupWindowError &popupWindowError )
- {
- // Any failure here is catastrophic...
-
- mFatalError = true;
- popupWindowError.HandleError ();
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::~CPopupWindowControl
- //
-
- CPopupWindowControl::~CPopupWindowControl(void)
- {
- long i; // used as an index
-
- if ( mIsIdling && mContainerSiteP )
- {
- // Remove our idler.
-
- mContainerSiteP->SetIdleTime ( RemoveAllIdlers, 0 );
- }
-
- mID[0] = 0;
-
- if ( mSourceName )
- {
- delete [] mSourceName;
- mSourceName = NULL;
- }
-
- if ( mNumDesiredSources > 0 )
- {
- // Get rid of the strings in our source name list.
-
- for ( i = 0; i < mNumDesiredSources; i++ )
- {
- ASSERT ( mDesiredSourceNames[i] != NULL, "Unexpected NULL source name.");
- delete [] mDesiredSourceNames[i];
- mDesiredSourceNames[i] = NULL;
- }
- mNumDesiredSources = -1;
- }
-
- if (mPict)
- {
- // Dispose the Picture, then the handle itself.
-
- ::DisposeHandle ( (Handle)((*mPict)->Pic) );
- ::DisposeHandle ( (Handle)mPict );
- mPict = NULL;
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::CBaseControl::IObjectWithSite::SetSite
- //
- STDMETHODIMP
- CPopupWindowControl::SetSite ( IUnknown* inClientSite )
- {
- HRESULT returnValue;
-
- returnValue = CBaseControl::SetSite ( inClientSite );
-
- if ( mContainerSiteP )
- {
- mIsIdling = SUCCEEDED ( mContainerSiteP->SetIdleTime ( 0, 0 ) );
- }
- else
- {
- mIsIdling = false;
- }
-
- return returnValue;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::IControl::Draw
- //
-
- STDMETHODIMP
- CPopupWindowControl::Draw ( DrawContext* Context )
- {
- HRESULT returnValue = ResultFromScode ( S_OK );
-
- if ( Context->DrawAspect != DVASPECT_CONTENT )
- {
- returnValue = ResultFromScode ( DV_E_DVASPECT );
- }
-
- return returnValue;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::CBaseControl::IControl::DoIdle
- //
-
- STDMETHODIMP
- CPopupWindowControl::DoIdle ( Uint32 IdleRefCon )
- {
- Boolean alreadyAdded;
- IConnectionPointContainer* cnxnPtContainer = NULL;
- IConnectionPoint* cnxnPt = NULL;
- char controlName[256];
- IEnumUnknown* enumUnknown;
- long i; // used as an index
- Boolean setAdviseSink;
- IUnknown* testControl;
-
- // if the client site has been set and we haven't yet tried to connect,
- // enumerate the other controls in this container to find the one we want
- // to connect to. We use the mConnectingComplete, mNumDesiredSources, and
- // mNumFoundSources to handle the case where some of the controls we're
- // attempting to connect to aren't enumerated yet because they haven't
- // loaded yet. Once we find all the ones we're looking for, we stop
- // looking.
- //
- // Note that we used to check to advisory cookie (mCookie) instead of
- // mConnectingComplete, but in our case now, we want to be able to connect
- // to multiple specific sources, so we need a separate flag.
-
- #pragma unused ( IdleRefCon )
-
- if ( mFatalError ) return ResultFromScode ( E_ABORT );
-
- // if we don't have a container yet
- // Get it now
- if ( !mContainerP )
- {
- mContainerSiteP->GetContainer(&mContainerP);
- mContainerP->AddRef();
- }
-
- if ( mContainerP && !mConnectingComplete )
- {
- try
- {
- // Enumerate the objects.
-
- if ( FAILED ( mContainerP->EnumControls ( NULL,
- OLECONTF_EMBEDDINGS,
- &enumUnknown ) ) )
- throw CPopupWindowError ( CANT_ENUM_OBJECTS_ERROR, this );
-
- while ( enumUnknown->Next ( 1, &testControl, NULL ) == NOERROR )
- {
- // Get the name. Do it here instead of in a more nested scope so that
- // we can use if for debugging.
-
- GetObjectName ( testControl, controlName );
-
- // Try to get a connection point container from the control.
-
- testControl->QueryInterface ( IID_IConnectionPointContainer,
- (void**) &cnxnPtContainer );
-
- if ( cnxnPtContainer )
- {
- // It has one, so this may be it. See if this connection point container
- // has a connection point with the outgoing interface we want.
-
- cnxnPtContainer->FindConnectionPoint ( IID_IDoMenuEvents, &cnxnPt );
-
- if ( cnxnPt )
- {
- // We got it, so set an advise connection on the outgoing interface.
-
- setAdviseSink = false;
-
- if ( mNumDesiredSources < 0 ) // We're not being specific.
- {
- // We don't really care about this if mNumDesiredSources < 0,
- // but we'll do it anyway for the sake of completeness.
-
- if ( !(AddSource ( controlName, &alreadyAdded )) )
- throw CPopupWindowError ( DATA_ALLOCATION_ERROR );
-
- setAdviseSink = true;
- }
- else
- {
- for ( i = 0; i < mNumDesiredSources; i++ )
- {
- ASSERT ( mDesiredSourceNames[i] != NULL,
- "Unexpected NULL source name!" );
- if ( STRINGS_ARE_EQUAL ( mDesiredSourceNames[i], controlName ) )
- {
- // It's one of our targets.
-
- if ( !(AddSource ( controlName, &alreadyAdded )) )
- throw CPopupWindowError ( DATA_ALLOCATION_ERROR );
-
- if ( !alreadyAdded )
- {
- // We don't want to set the advise sink if we've
- // found it in the past.
-
- setAdviseSink = true;
- }
-
- // There's no need to loop any further once we've matched.
-
- break;
- }
- }
- }
-
- if ( setAdviseSink )
- {
- if ( FAILED ( cnxnPt->Advise ( (IControl*)this, &mCookie ) ) )
- {
- throw CPopupWindowError ( CANT_ADVISE_CNXN_ERROR );
- }
- }
- }
-
- cnxnPtContainer->Release();
- }
- }
-
- // Set a reminder to indicate whether we've already done our connecting.
-
- mConnectingComplete = ( mNumDesiredSources < 0 ) ?
- true : ( mNumDesiredSources == mNumFoundSources );
-
- // Don't forget to release.
-
- enumUnknown->Release();
- }
-
- catch ( CPopupWindowError &popupWindowError )
- {
- // Any failure here is fatal, because if we can't connect we can't pop up.
-
- mFatalError = true;
- popupWindowError.HandleError ();
- }
- }
-
- if ( mConnectingComplete )
- {
- // We're hooked up, so discontinue idling.
-
- mContainerSiteP->SetIdleTime ( RemoveAllIdlers, 0 );
- mIsIdling = false;
- }
-
- if ( mPendingDraw )
- {
- // We have a draw pending, so force a draw.
-
- InvalAllContexts ();
- }
-
- return ResultFromScode ( S_OK );
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::OnStopBinding
- //
-
- STDMETHODIMP
- CPopupWindowControl::OnStopBinding(ErrorCode Result, const Char8* Error)
- {
- Rect boundsRect;
- HRESULT returnValue;
-
- if ( mFatalError ) return ResultFromScode ( E_ABORT );
-
- returnValue = CBaseBindStatusCallback::OnStopBinding ( Result, Error ); // shouldn't fail
-
- if (mBindSiteP)
- {
- mBindSiteP->Release(); // shouldn't fail
- mBindSiteP = 0;
- }
-
- // That should be end of file. Prepare the pict to be drawn.
-
- mPictIsLoaded = true;
-
- try
- {
- if ( ( mPict == NULL ) || ( (*mPict)->Pic == NULL ) )
- throw CPopupWindowError ( EOF_AND_NO_IMAGE_ERROR );
-
- boundsRect = (*(*mPict)->Pic)->picFrame;
- ::OffsetRect( &boundsRect, -boundsRect.left, -boundsRect.top );
- (*mPict)->PicRect = boundsRect;
-
- returnValue = ResultFromScode ( S_OK );
- }
-
- catch ( CPopupWindowError &popupWindowError )
- {
- // Any failure here is fatal, because if we don't have an image after
- // the data has all been delivered, there's nothing to pop up.
-
- mFatalError = true;
- popupWindowError.HandleError ();
-
- returnValue = ResultFromScode ( E_FAIL );
- }
-
- return returnValue;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::OnDataAvailable
- //
- // OnDataAvailable is a callback routine which gets called when there is data
- // available in the input stream. The amount of data is specified.
- // OnDataAvailable grabs "Size" bytes from the "StgMedium" (storage medium)
- // and places it into the target buffer mPict.
- //
- // OnDataAvailable will be called repeatedly until there is no more data
- // available in the input stream. Note that OnStopBinding gets called at EOF.
- //
- // This method increases the size of the inbut buffer handle "mPict" by "Size"
- // bytes each time it's called.
- //
-
- STDMETHODIMP
- CPopupWindowControl::OnDataAvailable(
- Uint32 BSCF,
- Uint32 Size,
- FORMATETC* FormatEtc,
- STGMEDIUM* StgMedium)
- {
- unsigned long newSize;
- HRESULT returnValue = ResultFromScode ( S_OK );
- Handle TargetPicHandle = NULL;
-
- if ( mFatalError ) return ResultFromScode ( E_ABORT );
-
- // CBaseBindStatusCallback::OnDataAvailable sets "mSize" based on "Size". (This should
- // never fail.)
-
- returnValue = CBaseBindStatusCallback::OnDataAvailable ( BSCF, Size, FormatEtc, StgMedium );
-
- if ( StgMedium->tymed == TYMED_FILE )
- {
- CoTaskMemFree ( StgMedium->lpszFileName );
- if ( StgMedium->pUnkForRelease != NULL )
- {
- StgMedium->pUnkForRelease->Release (); // Should not fail.
- }
- }
- else if ( StgMedium->tymed == TYMED_ISTREAM ) // Stream I/O
- {
- try
- {
- // Make sure that the picture record and its buffer are allocated and have
- // enough space to read the available data.
-
- if ( !(AllocatePictBuffer ()) ) throw CPopupWindowError ( DATA_ALLOCATION_ERROR );
-
- mPictBytesRemaining = mDataSize;
- if ( mPictBytesSoFar < cPictHeaderSize )
- {
- // Read the pict header. (Just read it into the PicHandle, and we'll
- // overwrite it when we get the real picture data.)
-
- if ( !(ReadPictHeader ( StgMedium )) )
- throw CPopupWindowError ( IMAGE_READ_ERROR );
-
- if ( mPictBytesSoFar >= cPictHeaderSize )
- {
- // We're going to throw away the header, so reset the buffer
- // handle size.
-
- TargetPicHandle = (Handle)((*mPict)->Pic);
- newSize = ::GetHandleSize ( TargetPicHandle ) - cPictHeaderSize;
- ::SetHandleSize ( TargetPicHandle, newSize );
-
- // Setting a handle smaller shouldn't fail...
-
- if ( ::GetHandleSize ( TargetPicHandle ) != newSize )
- throw CPopupWindowError ( DATA_REALLOCATION_ERROR );
- }
- }
-
- // It's possible we didn't read the entire picture header the first time, so
- // we can't assume it's okay to go ahead and start reading data.
-
- if ( ( mPictBytesSoFar >= cPictHeaderSize ) && ( mDataSize > 0 ) )
- {
- // Read the available data into the picture buffer.
-
- if ( !(ReadPictData ( StgMedium )) )
- throw CPopupWindowError ( IMAGE_READ_ERROR );
- }
- }
-
- catch ( CPopupWindowError &popupWindowError )
- {
- // Any failure here is fatal, because we don't have an image to pop up.
-
- mFatalError = true;
- popupWindowError.HandleError ();
-
- returnValue = ResultFromScode ( E_FAIL );
- }
- }
-
- return returnValue;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::IDoMenuEvents::Popup
- //
-
- STDMETHODIMP
- CPopupWindowControl::Popup ( IUnknown* Source, PlatformEvent* Event )
- {
- #pragma unused ( Source )
-
- DrawContext Context;
- GDHandle currentGraphicsDevice;
- GrafPtr currentGrafPort;
- pictInfo CurrentPict;
- EventRecord dummyEvent;
- StringPtr ErrorMessage = NULL;
- short innermost;
- Point mouseCoord;
- Rect myRect;
- RgnHandle oldClipRgn;
- Point screenBotRight;
- Rect screenRect;
- Point screenTopLeft;
-
- if ( mFatalError ) return ResultFromScode ( E_ABORT );
-
- // Get the target rect.
-
- mouseCoord = Event->where;
- ::GlobalToLocal ( &mouseCoord );
-
- SetRect ( &myRect, mouseCoord.h,
- mouseCoord.v,
- mouseCoord.h + mPopupWidth - 1,
- mouseCoord.v + mPopupHeight - 1);
-
- ::GetPort ( ¤tGrafPort );
-
- // Get the current screen information.
-
- currentGraphicsDevice = ::GetGDevice ();
- screenRect = (**currentGraphicsDevice).gdRect;
- ::SetPt ( &screenTopLeft, screenRect.left, screenRect.top + GetMBarHeight () );
- ::SetPt ( &screenBotRight, screenRect.right, screenRect.bottom );
- ::GlobalToLocal ( &screenTopLeft );
- ::GlobalToLocal ( &screenBotRight );
- ::Pt2Rect ( screenTopLeft, screenBotRight, &screenRect );
-
- //mPopupWidth = (screenRect.right - screenRect.left)/3; // 1/3 of screen size
- //mPopupHeight = (screenRect.bottom - screenRect.top)/3; // 1/3 of screen size
-
- // Force myRect onscreen and into the window.
-
- innermost = MIN ( currentGrafPort->portRect.bottom, screenRect.bottom );
- if ( myRect.bottom > innermost )
- {
- OffsetRect ( &myRect, 0, innermost - myRect.bottom );
- }
- innermost = MIN ( currentGrafPort->portRect.right, screenRect.right );
- if ( myRect.right > innermost )
- {
- OffsetRect ( &myRect, innermost - myRect.right, 0 );
- }
- innermost = MAX ( currentGrafPort->portRect.top, screenRect.top );
- if ( myRect.top < innermost )
- {
- OffsetRect ( &myRect, 0, innermost - myRect.top );
- }
- innermost = MAX ( currentGrafPort->portRect.left, screenRect.left );
- if ( myRect.left < innermost )
- {
- OffsetRect ( &myRect, innermost - myRect.left, 0 );
- }
-
- // Set the clip rect to myRect, including one pixel for the frame.
-
- ::InsetRect ( &myRect, -1, -1 );
- oldClipRgn = ::NewRgn ();
- ::GetClip ( oldClipRgn );
- ::ClipRect ( &myRect );
-
- ::FrameRect ( &myRect );
-
- // Draw inside the frame.
-
- ::InsetRect ( &myRect, 1, 1 );
- ::ClipRect ( &myRect );
-
- if ( mPictIsLoaded )
- {
- // Grab the pict handle from the pict info.
-
- CurrentPict = *(*mPict);
- if ( CurrentPict.Pic )
- {
- ::EraseRect ( &myRect );
- DrawPict ( currentGrafPort, &myRect, CurrentPict.Pic, &CurrentPict.PicRect );
-
- // Wait for a mouse or key event to happen. Note that we eat that event.
-
- Boolean done = false;
- while (!done)
- {
- WaitNextEvent ( everyEvent, &dummyEvent, 0, nil );
- switch ( dummyEvent.what )
- {
- case mouseDown:
- case keyDown:
- case autoKey:
- done = true;
- break;
- }
- }
-
- // Invalidate the rect so it gets redrawn.
-
- ::InsetRect ( &myRect, -1, -1 ); // To get the frame, too.
- ::InvalRect ( &myRect);
- }
- else
- {
- ErrorMessage = "\pNot Enough Ram to store picture.";
- }
- }
- else
- {
- ErrorMessage = "\pPicture not loaded yet.";
- }
-
- if ( ErrorMessage )
- {
- mDrawPort = (GrafPtr)(Context.Port);
- mPendingDraw = true;
-
- // Draw the error message.
-
- ::TextFace ( bold );
- ::TextFont ( 0 );
- ::TextSize ( 12 );
- ::MoveTo (
- (Context.Location.right +
- Context.Location.left -
- StringWidth(ErrorMessage))/2,
- (Context.Location.bottom + Context.Location.top + 12)/2 );
- ::DrawString ( ErrorMessage );
- }
- else
- {
- // Stop invalidating the popup rect.
-
- mPendingDraw = false;
- }
-
- // Restore the old clipping region before we go.
-
- ::SetClip ( oldClipRgn );
- ::DisposeRgn ( oldClipRgn );
-
- return ResultFromScode ( S_OK );
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::IPersistPropertyBag::Load
- //
-
- STDMETHODIMP
- CPopupWindowControl::Load ( IPropertyBag* PropBag, IErrorLog* ErrorLog )
- {
- LPVOID dummy;
- long i; // used for an index
- DWORD length;
- char propertyNameString[64];
- char propertyString[Str255BufferLength];
- HRESULT returnValue = ResultFromScode ( S_OK );
- LPMONIKER URLMoniker = NULL;
- VARIANT v;
-
- if ( mFatalError ) return ResultFromScode ( E_ABORT );
-
- // Try to load in each property. If we can't get it, then leave things at the default.
- // Loop through all the sourceobject[x] parameters. It's possible there's only one,
- // with no [x].
-
- strcpy ( propertyNameString, cSourceObjectStr );
-
- try
- {
- if ( ::LoadPropertyString (
- PropBag, propertyNameString, propertyString, Str255StringLength, ErrorLog ) )
- {
- if ( !(AddDesiredSourceName ( propertyString )) )
- throw CPopupWindowError ( DATA_ALLOCATION_ERROR );
- }
- else
- {
- for ( i = 0; i <= cMaxNumSourceControls; i++ )
- {
- sprintf ( propertyNameString, "%s[%ld]", cSourceObjectStr, i );
- if ( ::LoadPropertyString (
- PropBag, propertyNameString, propertyString, Str255StringLength, ErrorLog ) )
- {
- if ( !(AddDesiredSourceName ( propertyString )) )
- throw CPopupWindowError ( DATA_ALLOCATION_ERROR );
- }
- }
- }
-
- v.vt = VT_BSTR;
- v.bstrVal = NULL;
-
- // Try to load in the property. If we can't get it, then leave things at their default.
-
- PropBag->Read ( "data", &v, ErrorLog );
-
- if ( v.bstrVal )
- {
- length = *((LPDWORD)(v.bstrVal)) ;
- strcpy ( (Char8*)mDataURL, v.bstrVal + sizeof(Uint32) );
- CoTaskMemFree ( v.bstrVal );
- }
-
- mUnkOuterP->QueryInterface ( IID_IBindHost, (LPVOID *) &mBindSiteP );
-
- if ( mBindSiteP )
- {
- mBindSiteP->CreateMoniker ( (LPOLESTR)mDataURL, NULL, &URLMoniker, 0 );
- if( URLMoniker )
- {
- mBindSiteP->MonikerBindToStorage ( URLMoniker, NULL, this, IID_IStream, &dummy );
- URLMoniker->Release ();
- }
- }
- }
-
- catch ( CPopupWindowError &popupWindowError )
- {
- // Any failure here is fatal, because we couldn't load the control parameters.
-
- mFatalError = true;
- popupWindowError.HandleError ();
-
- returnValue = ResultFromScode ( E_FAIL );
- }
-
- return returnValue;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::IUnknown::QueryInterface
- //
- // Returns a pointer to the specified interface on a component to which a
- // client currently holds an interface pointer.
- //
-
- STDMETHODIMP
- CPopupWindowControl::QueryInterface(REFIID RefID, void** Obj)
- {
- HRESULT returnValue = ResultFromScode ( S_OK );
-
- if ( mFatalError ) return ResultFromScode ( E_ABORT );
-
- if ( RefID == IID_IDoMenuEvents ) // an incoming interface
- {
- *Obj = (void*)((IDoMenuEvents*)this);
- AddRef ();
- }
- else
- {
- returnValue = CBaseControl::QueryInterface ( RefID, Obj );
- }
-
- return returnValue;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::SetName
- //
- // SetName returns true if it successfully sets the name, false otherwise. It
- // can fail to allocate memory for the name.
-
- Boolean CPopupWindowControl::SetName ( const char * theName )
- {
- strcpy ( (char*)(&mID[1]), theName );
- mID[0] = strlen(theName);
-
- return true;
-
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::SetSourceName
- //
- Boolean CPopupWindowControl::SetSourceName ( const char * theName )
- {
- Boolean returnValue = true;
-
- try
- {
- if ( mSourceName == NULL )
- {
- mSourceName = (char *) new char[Str255BufferLength];
- if ( mSourceName == NULL ) throw CPopupWindowError ( DATA_ALLOCATION_ERROR );
- }
-
- strcpy ( mSourceName, theName );
- }
-
- catch ( CPopupWindowError &popupWindowError )
- {
- // Any failure here is fatal, because we won't be able to connect to another
- // control by name.
-
- mFatalError = true;
- popupWindowError.HandleError ();
-
- returnValue = false;
- }
-
- return returnValue;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::AddDesiredSourceName
- //
- // AddDesiredSourceName returns true if it successfully added the name to the
- // array of source names, false otherwise.
- //
- Boolean CPopupWindowControl::AddDesiredSourceName ( const char * theName )
- {
- long currentIndex;
- long nextIndex;
- Boolean returnValue = true;
-
- ASSERT ( theName != NULL, "Unexpected NULL source name in AddDesiredSourceName" );
-
- currentIndex = ( mNumDesiredSources < 0 ) ? 0 : mNumDesiredSources;
- nextIndex = currentIndex + 1;
-
- if ( nextIndex < cMaxNumSourceControls )
- {
- try
- {
- mDesiredSourceNames[currentIndex] = new char[strlen(theName)+1];
- if ( mDesiredSourceNames[currentIndex] == NULL )
- throw CPopupWindowError ( DATA_ALLOCATION_ERROR );
-
- strcpy(mDesiredSourceNames[currentIndex], theName);
- mNumDesiredSources = nextIndex;
- }
-
- catch ( CPopupWindowError &popupWindowError )
- {
- // Any failure here is fatal, because we don't another control to connect to.
-
- mFatalError = true;
- popupWindowError.HandleError ();
-
- returnValue = false;
- }
- }
-
- return returnValue;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::AddSource
- //
- // AddSource sets the alreadyFoundIt parameter to true if it already exists in
- // the list.
- //
- // AddSource returns false if it has an allocation error, true otherwise.
-
- Boolean CPopupWindowControl::AddSource ( const char * sourceName, Boolean * alreadyFoundIt )
- {
- long i; // used as an index
- Boolean returnValue = true;
-
- // Only add the source to our list of found sources if we haven't already done so.
-
- *alreadyFoundIt = false;
-
- for ( i = 0; i < mNumFoundSources; i++ )
- {
- if ( STRINGS_ARE_EQUAL ( mFoundSourceNames[i], sourceName ) )
- {
- // It's already in our list.
-
- *alreadyFoundIt = true;
- break;
- }
- }
-
- if ( !(*alreadyFoundIt) )
- {
- try
- {
- mFoundSourceNames[mNumFoundSources] = new char[strlen(sourceName)+1];
- if ( mFoundSourceNames[mNumFoundSources] == NULL)
- throw CPopupWindowError ( DATA_ALLOCATION_ERROR );
-
- strcpy(mFoundSourceNames[mNumFoundSources], sourceName);
- mNumFoundSources++;
- }
-
- catch ( CPopupWindowError &popupWindowError )
- {
- // Any failure here is fatal, because we don't have a source control.
-
- mFatalError = true;
- popupWindowError.HandleError ();
-
- returnValue = false;
- }
- }
-
- return returnValue;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::IsSource
- //
- Boolean CPopupWindowControl::IsSource ( IUnknown * unk )
- {
- Boolean isSource = false;
- char sourceName[256];
-
- if ( mNumDesiredSources == -1 ) // We're not being specific.
- {
- isSource = true;
- }
- else
- {
- GetObjectName ( unk, sourceName );
-
- if ( sourceName )
- {
- isSource = IsSource ( sourceName );
- }
- }
-
- return isSource;
- }
-
- Boolean CPopupWindowControl::IsSource ( const char * sourceName )
- {
- long i; // used as an index
- Boolean isSource = false;
-
- if ( mNumDesiredSources == -1 ) // We're not being specific.
- {
- isSource = true;
- }
- else
- {
- for ( i = 0; i < mNumFoundSources; i++ )
- {
- ASSERT(mFoundSourceNames[i] != NULL, "Unexpected NULL source name!");
-
- if ( STRINGS_ARE_EQUAL ( mFoundSourceNames[i], sourceName ) )
- {
- // It's one of our targets.
-
- isSource = true;
- break; // There's no need to loop any further once we've matched.
- }
- }
- }
-
- return isSource;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::DrawPict
- //
-
- void CPopupWindowControl::DrawPict (
- GrafPtr pGrafDraw,
- Rect* lprect,
- PicHandle Pic,
- Rect* PictRect)
- {
-
- #pragma unused (pGrafDraw)
-
- Rect theRect;
-
- theRect.top = lprect->top;
- theRect.left = lprect->left;
- theRect.bottom = lprect->top + PictRect->bottom;
- theRect.right = lprect->left + PictRect->right;
-
- ::DrawPicture ( Pic, &theRect );
-
- return;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::AllocatePictBuffer
- //
- // AllocatePictBuffer allocates a buffer in memory before the picture is read
- // in, and each time new data is available AllocatePictBuffer bumps up the
- // buffer size.
- //
- // AllocatePictBuffer returns true if the allocation was successful, false
- // otherwise.
- //
- Boolean CPopupWindowControl::AllocatePictBuffer ( void )
- {
- unsigned long newSize;
- Boolean returnValue = true;
- Handle TargetPicHandle = NULL;
-
- try
- {
- if ( ( mPict == NULL) && ( mDataSize > 0 ) )
- {
- // Allocate memory for a new picture record and its buffer.
-
- mPict = (pictInfo**)(::NewHandle ( sizeof(pictInfo) ));
- if ( mPict == NULL ) throw CPopupWindowError ( DATA_ALLOCATION_ERROR );
-
- ::HLock ( (Handle)mPict );
- (**mPict).Pic = (PicHandle)(::NewHandle ( mDataSize ));
- ::HUnlock( (Handle)mPict );
- if ( (**mPict).Pic == NULL ) throw CPopupWindowError ( DATA_ALLOCATION_ERROR );
-
- // Let everyone know we're just starting.
-
- mPictIsLoaded = false;
- mPictBytesSoFar = 0;
- }
- else if ( mDataSize > 0 ) // ( mPict != NULL ); don't bother if the amount of data
- { // available is zero.
- if ( (**mPict).Pic != NULL )
- {
- // Bump up the memory for the picture buffer so we have space to read into.
-
- TargetPicHandle = (Handle)((*mPict)->Pic);
- ::SetHandleSize ( TargetPicHandle, mPictBytesSoFar + mDataSize );
- newSize = ::GetHandleSize ( TargetPicHandle );
- if ( newSize != mPictBytesSoFar + mDataSize )
- throw CPopupWindowError ( DATA_REALLOCATION_ERROR );
- }
- }
- }
-
- catch ( CPopupWindowError &popupWindowError )
- {
- // Any failure here is fatal; because if we don't have enough memory
- // for an image buffer, we can't render the image. Duh.
-
- mFatalError = true;
- popupWindowError.HandleError ();
-
- returnValue = false;
- }
-
- return returnValue;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::ReadPictHeader
- //
- // ReadPictHeader reads the pict header from the input stream into the pict
- // buffer.
- //
- // ReadPictHeader is called by the OnDataAvailable callback, so it is possible
- // all of the data isn't available when ReadPictHeader is called. If not, it
- // will continue reading when it is called repeatedly until all of the pict
- // header has been read.
- //
- // ReadPictHeader returns true if successful, false otherwise.
- //
- Boolean CPopupWindowControl::ReadPictHeader ( STGMEDIUM* StorageMedium )
- {
- unsigned long actualBytesRead = 0;
- unsigned long BytesToRead = 0L;
- unsigned long headerBytesRemaining = 0;
- HRESULT resultCode = ResultFromScode ( S_OK );
- Boolean returnValue = true;
- char* Target = NULL;
- Handle TargetPicHandle = NULL;
-
- TargetPicHandle = (Handle)((*mPict)->Pic);
- ::HLock ( TargetPicHandle );
- Target = *TargetPicHandle;
-
- headerBytesRemaining = ( cPictHeaderSize - mPictBytesSoFar > 0 ) ?
- cPictHeaderSize - mPictBytesSoFar : 0;
- BytesToRead = ( headerBytesRemaining < mDataSize ) ? headerBytesRemaining : mDataSize;
-
- try
- {
- resultCode = StorageMedium->pstm->Read ( Target,
- BytesToRead,
- &actualBytesRead );
- ::HUnlock ( TargetPicHandle );
-
- if ( FAILED ( resultCode ) ) throw CPopupWindowError ( IMAGE_READ_ERROR );
-
- mPictBytesRemaining -= actualBytesRead;
- mPictBytesSoFar += actualBytesRead;
- }
-
- catch ( CPopupWindowError &popupWindowError )
- {
- // Are we guaranteed that a failure here is fatal?
-
- mFatalError = true;
- popupWindowError.HandleError ();
-
- returnValue = false;
- }
-
- return returnValue;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupWindowControl::ReadPictData
- //
- // ReadPictData reads the pict data from the input stream into the pict buffer.
- //
- // ReadPictData is called by the OnDataAvailable callback, so it is possible
- // all of the data isn't available when ReadPictData is called. If not, it
- // will continue reading when it is called repeatedly until all of the pict
- // data has been read.
- //
- // ReadPictData returns true if it is successful, false otherwise.
- //
- Boolean CPopupWindowControl::ReadPictData ( STGMEDIUM* StorageMedium )
- {
- unsigned long actualBytesRead = 0;
- unsigned long BytesToRead = 0L;
- HRESULT resultCode = S_OK;
- Boolean returnValue = true;
- char* Target = NULL;
- Handle TargetPicHandle = NULL;
-
- // Read the available data into the picture buffer.
-
- TargetPicHandle = (Handle)((*mPict)->Pic);
- ::HLock ( TargetPicHandle );
-
- BytesToRead = mPictBytesRemaining;
-
- // Advance the target through the PicHandle as we go. Note that we overwrite
- // the pict header data we previously read into the target buffer.
-
- Target = *TargetPicHandle + mPictBytesSoFar - cPictHeaderSize;
-
- try
- {
- resultCode = StorageMedium->pstm->Read ( Target,
- BytesToRead,
- &actualBytesRead );
- ::HUnlock ( TargetPicHandle );
- if ( FAILED ( resultCode ) ) throw CPopupWindowError ( IMAGE_READ_ERROR );
-
- mPictBytesRemaining -= actualBytesRead;
- mPictBytesSoFar += actualBytesRead;
- }
-
- catch ( CPopupWindowError &popupWindowError )
- {
- // Are we guaranteed that a failure here is fatal?
-
- mFatalError = true;
- popupWindowError.HandleError ();
-
- returnValue = false;
- }
-
- return returnValue;
- }
-